#include "aos/kernel.h"
#include "ulog/ulog.h"
#include "lidar.h"
#include "canbus.h"
#include "aos/cli.h"
#include "canopen/io_board_api.h"

static uint8_t default_output[8] = {0};
uint8_t g_input_l[3] = {0};

static void io_board_state_change_cb(const uint8_t board_id, const io_board_state_t state)
{
    char board_version_show[64];
    memset(board_version_show, 0, sizeof(board_version_show));
    switch (state)
    {
    case io_board_working:

        inquire_io_board_version(board_id, board_version_show, sizeof(board_version_show));
        LOGI("APP", "Board %d Is Working, input cnt %d output cnt %d VER %s",
            board_id,
            get_io_board_input_cnt(board_id), /* this is only for demo, DONOT recomend call API in any LOG */
            get_io_board_output_cnt(board_id), board_version_show);

        if(0==get_gpio_output_default(board_id, sizeof(default_output), default_output)) {
            LOGI("APP", "Board %d Default Output 0x%x, 0x%x, 0x%x, 0x%x",
                board_id,default_output[0], default_output[1], default_output[2], default_output[3]);
        } else {
            LOGE("APP", "Board %d Get Default Output Failed", board_id);
        }
        break;

    case io_board_lost_connection:
        LOGE("APP", "Board %d Turn to lost connect, check the power or connection", board_id);
        break;

    default:
        break;
    }
}

static void input_change_cb(const uint8_t board_id, const uint8_t input_data_len, const uint8_t *input_level)
{
	//g_input_l[0] = input_level[0];
	//g_input_l[1] = input_level[1];
	//g_input_l[2] = input_level[2];
	
    uint8_t i = 0;
    char tmp_buf[128];
    uint8_t tmp_buf_data_cnt = 0;
    memset(tmp_buf, 0, sizeof(tmp_buf));
    for (; i < input_data_len; i++) {
        tmp_buf_data_cnt += snprintf(&tmp_buf[tmp_buf_data_cnt], 128 - tmp_buf_data_cnt, "0x%x ", input_level[i]);
    }

    LOGI("APP", "Board %d GPIO Input Change, Byte Count %d, Level %s",
        board_id, input_data_len, tmp_buf);

}

static void co_master_cmd_routine(char *buf, int len, int argc, char **argv)
{
    if (argc == 4) {
        int board_id = -1;
        int pin_number = -1;

        board_id = strtoul(argv[1], NULL, 10);
        pin_number = strtoul(argv[2], NULL, 10);

        if (-1 != board_id && -1 != pin_number) {

                switch (*(argv[3]))
                {
                case 'i':
                    aos_cli_printf("Board %d pin %d input state %d\r\n", board_id, pin_number, inquire_gpio_input(board_id, pin_number));
                        break;

                case 'o':
                    aos_cli_printf("Board %d pin %d output state %d\r\n", board_id, pin_number, inquire_gpio_output(board_id, pin_number));
                        break;

                case '1':
                    aos_cli_printf("Set Board %d pin %d\r\n", board_id, pin_number);
                    gpio_output(board_id, pin_number, 1);
                    break;

                case '0':
                    aos_cli_printf("Clear Board %d pin %d\r\n", board_id, pin_number);
                    gpio_output(board_id, pin_number, 0);
                    break;

                case 'd': {/* set default output value */
                    uint8_t def_output_setting[4] = {0x80, 0xA0, 0, 0};
                    int32_t rc = set_gpio_output_default(board_id, sizeof(def_output_setting), def_output_setting);
                    aos_cli_printf("Set Board %d Default output Rlt %d\r\n", board_id, rc);
                }
                    break;

                case 'b': {
                    uint16_t board_output_cnt = get_io_board_output_cnt(board_id);
                    if(0xFFFF!=board_output_cnt){
                        uint8_t setting_output_batch[4] = {0xAA, 0x55, 0x0, 0x0};
                        int32_t rc = set_gpio_output_batch(board_id, setting_output_batch, 0, board_output_cnt);
                        aos_cli_printf("Batch Set Board %d Output Rlt %d\r\n", board_id, rc);
                    } else {
                        aos_cli_printf("Batch Set Board %d Output Failed as not get output cnt yet\r\n", board_id);
                    }
                }
								break;

                default:
                    aos_cli_printf("Board %d pin %d Unknown cs %d\r\n", board_id, pin_number, *(argv[3]));
                    break;
                }

        }

    } else {
        aos_cli_printf("CMD like io board_id pin-number cs\r\n");
    }

}

static struct cli_command co_master_cmd[] = {
    { "io","control or get status of IO board", co_master_cmd_routine },
};

void iomaster_init(void)
{
	io_board_manager_init(io_board_state_change_cb, input_change_cb);
    aos_cli_register_commands(&co_master_cmd[0], sizeof(co_master_cmd) / sizeof(struct cli_command));
}

